#include "ft6336.h"

#include "gpio_ctl.h"

#include "lvgl.h"
#include "esp_log.h"
#include "driver/i2c.h"
#include "freertos/task.h"
#include "freertos/FreeRTOS.h"


#define FT6336_LCD_HOR_VER_SIGN    2	 // 0:横屏, 1:与0相反的横屏
                                         // 2:竖屏, 3:与2相反的竖屏
#if (FT6336_LCD_HOR_VER_SIGN == 0) 	// 0:横屏
// 宽, 高
#define FT6336_LCD_H_RES   			480                      
#define FT6336_LCD_V_RES   			320   
#define _LV_FT6X36_SWAPXY        	1
#define _LV_FT6X36_INVERT_X        	1
#define _LV_FT6X36_INVERT_Y        	0

#elif (FT6336_LCD_HOR_VER_SIGN == 1) 	// 0:横屏
// 宽, 高
#define FT6336_LCD_H_RES   			480                      
#define FT6336_LCD_V_RES   			320   
#define _LV_FT6X36_SWAPXY        	1
#define _LV_FT6X36_INVERT_X        	0
#define _LV_FT6X36_INVERT_Y        	1

#elif(FT6336_LCD_HOR_VER_SIGN == 2)	// false:竖屏													 
#define FT6336_LCD_H_RES  			320                       
#define FT6336_LCD_V_RES   			480
#define _LV_FT6X36_SWAPXY         	0
#define _LV_FT6X36_INVERT_X         1
#define _LV_FT6X36_INVERT_Y         1

#elif(FT6336_LCD_HOR_VER_SIGN == 3)	// false:竖屏													 
#define FT6336_LCD_H_RES  			320                       
#define FT6336_LCD_V_RES   			480
#define _LV_FT6X36_SWAPXY         	0
#define _LV_FT6X36_INVERT_X         0
#define _LV_FT6X36_INVERT_Y         0

#endif


static bool ft6336_Init(void);
static bool ft6336_scan(void);
static void ft6336_read_reg(uint16_t reg, uint8_t *buf, uint8_t len);

static esp_err_t i2c_write_reg_8bit(uint8_t reg_addr);
static esp_err_t i2c_read_reg_n(uint8_t reg_addr, uint8_t* buffer, size_t len);

_m_tp_dev tp_dev;
const char* TAG = "FT6336";

// 写入寄存器指令
static esp_err_t i2c_write_reg_8bit(uint8_t reg_addr)
{
    i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
    i2c_master_start(i2c_cmd);
    i2c_master_write_byte(i2c_cmd, (FT6236_I2C_SLAVE_ADDR << 1) | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(i2c_cmd, reg_addr, true);
    // i2c_master_write_byte(i2c_cmd, data, true);
    i2c_master_stop(i2c_cmd);
    esp_err_t ret = i2c_master_cmd_begin(TOUCH_I2C_PORT, i2c_cmd, I2C_RE_WR_MS / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(i2c_cmd);
    return ret;
}

// 读取不固定长度数据
static esp_err_t i2c_read_reg_n(uint8_t reg_addr, uint8_t* buffer, size_t len)
{
    if (len == 0) {
        return ESP_OK;
    }

    i2c_cmd_handle_t i2c_cmd = i2c_cmd_link_create();
    i2c_master_start(i2c_cmd);
    i2c_master_write_byte(i2c_cmd, (FT6236_I2C_SLAVE_ADDR << 1) | I2C_MASTER_WRITE, true);
    i2c_master_write_byte(i2c_cmd, reg_addr, true);
    i2c_master_start(i2c_cmd);
    i2c_master_write_byte(i2c_cmd, (FT6236_I2C_SLAVE_ADDR << 1) | I2C_MASTER_READ, true);

    if (len > 1) {
        i2c_master_read(i2c_cmd, buffer, len - 1, I2C_MASTER_ACK);
    }

    i2c_master_read_byte(i2c_cmd, buffer + len - 1, I2C_MASTER_LAST_NACK);
    i2c_master_stop(i2c_cmd);
    esp_err_t ret = i2c_master_cmd_begin(TOUCH_I2C_PORT, i2c_cmd, I2C_RE_WR_MS / portTICK_PERIOD_MS);
    i2c_cmd_link_delete(i2c_cmd);
    return ret;
}

// 读取ft6336寄存器中数据
static void ft6336_read_reg(uint16_t reg, uint8_t *buf, uint8_t len)
{
	esp_err_t err_ret = i2c_write_reg_8bit(FT_CMD_WR);
	err_ret |= i2c_write_reg_8bit((reg & 0xff));
	err_ret |= i2c_write_reg_8bit(FT_CMD_RD);
	err_ret |= i2c_read_reg_n(reg, buf, len);

	if(err_ret != ESP_OK){
		ESP_LOGI(TAG, "ft6336_read_reg failed, err:%s", esp_err_to_name(err_ret));
	}
} 

// 初始化ft6336		
static bool ft6336_Init(void)
{
	uint8_t temp[2] = {0};
	
	gpio_in(FT_INT, 0); 					// 将中断管脚设置为输入模式
	gpio_out(FT_RST, 0);					// 复位
	vTaskDelay(pdMS_TO_TICKS(10));
	gpio_out(FT_RST, 1);    				// 释放复位	
	vTaskDelay(pdMS_TO_TICKS(500));

//	temp[0]=0;
//	FT6336_WR_Reg(FT_DEVIDE_MODE,temp,1);	//进入正常操作模式 
//	FT6336_WR_Reg(FT_ID_G_MODE,temp,1);		//查询模式 
	//temp[0]=40;								//触摸有效值，22，越小越灵敏	
	//FT6336_WR_Reg(FT_ID_G_THGROUP,temp,1);	//设置触摸有效值
	ft6336_read_reg(FT_ID_G_FOCALTECH_ID, &temp[0],1);
	if(temp[0] != 0x11){
		return false;
	}
	ft6336_read_reg(FT_ID_G_CIPHER_MID, &temp[0], 2);
	if(temp[0] != 0x26){
		return false;
	}
	if((temp[1] != 0x00) && (temp[1] != 0x01) && (temp[1] != 0x02)){
		return false;
	}
	ft6336_read_reg(FT_ID_G_CIPHER_HIGH,&temp[0],1);
	if(temp[0]!=0x64){
		return false;
	}
//	temp[0]=12;								//激活周期，不能小于12，最大14
//	FT6336_WR_Reg(FT_ID_G_PERIODACTIVE,temp,1); 
	//读取版本号，参考值：0x3003
//	ft6336_read_reg(FT_ID_G_LIB_VERSION,&temp[0],2);  
//	if(temp[0]==0X10&&temp[1]==0X01)//版本:0X3003
//	{ 
//		printf("CTP ID:%x\r\n",((uint16_t)temp[0]<<8)+temp[1]);
//		return 0;
//	} 
	return true;
}

const uint16_t ft6336_tpx_tbl[2]={FT_TP1_REG, FT_TP2_REG};

// 扫描ft6336被触摸后的坐标值
static bool ft6336_scan(void)
{
	uint8_t buf[4] = {0};
	uint8_t i = 0;
	
	for(i = 0; i < CTP_MAX_TOUCH; ++i) {
		ft6336_read_reg(ft6336_tpx_tbl[i], buf, 4);		//读取XY坐FT6336_LCD_V_RES标值 
		
		tp_dev.x[i] = ((buf[0] & 0X0F) << 8) + (buf[1] & 0xFF);
		tp_dev.y[i] = ((buf[2] & 0X0F) << 8) + (buf[3] & 0xFF);

#if _LV_FT6X36_SWAPXY
		int16_t swap_buf = tp_dev.x[i];
    	tp_dev.x[i] = tp_dev.y[i];
    	tp_dev.y[i] = swap_buf;
#endif

#if _LV_FT6X36_INVERT_X
    	tp_dev.x[i] = FT6336_LCD_H_RES - tp_dev.x[i];
#endif

#if _LV_FT6X36_INVERT_Y
    	tp_dev.y[i] = FT6336_LCD_V_RES - tp_dev.y[i];
#endif

		if(tp_dev.x[i] > FT6336_LCD_H_RES && tp_dev.y[i] > FT6336_LCD_V_RES){
			return false;
		}
	}

	return true;			
}

// 扫描回调函数 
static void lvgl_ft6336_touch_cb(lv_indev_drv_t *drv, lv_indev_data_t *data)
{
	uint8_t mode = 0;

	ft6336_read_reg(FT_REG_NUM_FINGER, &mode, 1);//读取触摸点的状态
	if(mode == 1){
		if (ft6336_scan()) {
			char str[4] = "";
			uint8_t i = 0;
			for(i = 0; i < CTP_MAX_TOUCH && tp_dev.x[i] != 0 && tp_dev.y[i] ; ++i){
				if(tp_dev.x[i] <= FT6336_LCD_H_RES && tp_dev.y[i] <= FT6336_LCD_V_RES) {
					itoa(i, str, 4);
					data->point.x = tp_dev.x[i];
					data->point.y = tp_dev.y[i];
					ESP_LOGI(TAG, "touch_point%s: X1:%d, Y1:%d", str, tp_dev.x[i], tp_dev.y[i]);
					data->state = LV_INDEV_STATE_PRESSED;
				} else{
					tp_dev.x[i] = 0xffff;
					tp_dev.y[i] = 0xffff;
				}
		    }
		}
   } else {	
		for(uint8_t i = 0; i < CTP_MAX_TOUCH; i++) {
			tp_dev.x[i] = 0xffff;
			tp_dev.y[i] = 0xffff;
		}
		tp_dev.sta &= 0XE0;	//清除点有效标记	
		data->state = LV_INDEV_STATE_RELEASED;
	}
}

// extern lv_disp_t *disp; /*Descriptor of a display driver*/
void lv_f6336_init(void)
{	
	// 配置I2C总线
	i2c_config_t i2c_config = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };

	esp_err_t ret_err = i2c_param_config(TOUCH_I2C_PORT, &i2c_config);
    // 初始化I2C总线
	if(ret_err == ESP_OK){
		ret_err = i2c_driver_install(TOUCH_I2C_PORT, i2c_config.mode, 0, 0, 0);
		if(ret_err != ESP_OK){
			ESP_LOGI(TAG, "i2c failed");
		}
	}
   
	if(ft6336_Init()){
		ESP_LOGI(TAG, "successful");
	}else{
		ESP_LOGI(TAG, "failed");
	}

    static lv_indev_drv_t indev_drv;
    lv_disp_t *disp = lv_disp_get_default();
    lv_indev_drv_init(&indev_drv);
    indev_drv.type = LV_INDEV_TYPE_POINTER;
    indev_drv.disp = disp;
    indev_drv.read_cb = lvgl_ft6336_touch_cb;

    lv_indev_drv_register(&indev_drv);
}


